/**
 * Filename : SocketDemo.java
 * Author : morris
 * Creation time : 2013-4-19 上午10:57:56
 * Description : 
 */
package cn.com.sbell.vss.csg.heartbeat;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;

public class SocketDemo {
	// 消息属性格式:return properties:Type-Reserved-Length-Value

	// 消息由消息头和消息体组成.消息体中包括多个消息属性.
	private final static int VERSION = 0x10;
	private final static int RESERVEDVALUE = 0;

	// 各消息属性type字段需要填的值
	private final static int ACK_TYPE = 0;
	private final static int SERVER_NAME = 1;
	private final static int SERVER_ID = 2;
	private final static int SERVER_IP = 3;
	private final static int INTERVAL = 4;
	// 增加设备接入码的属性值为9
	private final static int PU_PASSWORD = 9;
	private final static int SERVER_TYPE = 10;

	// 各个消息属性大小(字节)
	private final static int TYPE_LENGTH = 1;
	private final static int RESERVED_LENGTH = 1;
	private final static int LENGTH_LENGTH = 2;
	private final static int COMMON_PART_LENGTH = TYPE_LENGTH + RESERVED_LENGTH
			+ LENGTH_LENGTH;

	private final static int SERVERIP_IP_LENGTH = 4;
	private final static int SERVERIP_PORT_LENGTH = 2;
	private final static int SERVERIP_RESERVED_LENGTH = 2;
	private final static int SERVERIP_VALUE_LENGTH = SERVERIP_IP_LENGTH
			+ SERVERIP_PORT_LENGTH + SERVERIP_RESERVED_LENGTH;
	private final static int SERVERIP_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERIP_VALUE_LENGTH;

	private final static int SERVERID_VALUE_LENGTH = 20;
	private final static int SERVERID_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERID_VALUE_LENGTH;

	private final static int SERVERNAME_VALUE_LENGTH = 10;
	private final static int SERVERNAME_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERNAME_VALUE_LENGTH;

	private final static int ACCESSPWD_VALUE_LENGTH = 10;
	private final static int ACCESSPWD_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ ACCESSPWD_VALUE_LENGTH;

	private final static int SERVERTYPE_VALUE_LENGTH = 8;
	private final static int SERVERTYPE_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERTYPE_VALUE_LENGTH;

	private final static int INTERVAL_VALUE_LENGTH = 2;
	private final static int INTERVAL_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ INTERVAL_VALUE_LENGTH;

	private final static int ACKTYPE_VALUE_LENGTH = 1;
	private final static int ACKTYPE_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ ACKTYPE_VALUE_LENGTH;

	// 消息总大小.
	private final static int HEAD_LENGTH = 4;
	private final static int BODY_LENGTH = SERVERIP_TOTAL_LENGTH
			+ SERVERID_TOTAL_LENGTH + SERVERNAME_TOTAL_LENGTH
			+ ACCESSPWD_TOTAL_LENGTH + SERVERTYPE_TOTAL_LENGTH
			+ INTERVAL_TOTAL_LENGTH + ACKTYPE_TOTAL_LENGTH;
	private final static int TOTAL_LENGTH = HEAD_LENGTH + BODY_LENGTH;

	public byte[] createTCPdata() {
		HeartBeatMessage msg = new HeartBeatMessage();
		// msg.setMessageType(HeartBeatMessage.REGISTER);
		msg.setMessageType(HeartBeatMessage.HEARTBEAT);
		msg.setPort(80);
		msg.setServerId("090110000103520001");
		msg.setServerIp("192.168.6.149");
		msg.setAccessPassword("admin");
		msg.setServerName("admin");
		msg.setServerType("VS");
		msg.setPeriod(3000);
		msg.setNeedAcknowledge(true);

		ByteBuffer buf = ByteBuffer.allocate(TOTAL_LENGTH);
		System.out.println("allocate total length " + TOTAL_LENGTH);
		// buf.setAutoExpand(true);

		// 消息头部分
		buf.put((byte) VERSION);// 版本号
		buf.put((byte) (msg.getMessageType()));// 请求的消息类型
		int totalLength = getTotalLength(msg);
		System.out.println("msg length = " + totalLength);
		buf.putShort((short) totalLength);// 消息头和消息体的全部长度

		// 消息体部分
		// ACK_TYPE
		putACKTypeIntoBuffer(msg, buf);
		// INTERVAL
		putIntervalIntoBuffer(msg, buf);
		// SERVER_NAME
		if (null != msg.getServerName()) {
			putServerNameIntoBuffer(msg, buf);
		}
		// SERVER_ID
		if (null != msg.getServerId()) {
			putServerIdIntoBuffer(msg, buf);
		}
		// SERVER_IP
		if (null != msg.getServerIp()) {
			putServerIpIntoBuffer(msg, buf);
		}
		// PU_PASSWORD
		if (null != msg.getAccessPassword()) {
			putAccessPasswordIntoBuffer(msg, buf);
		}
		// SERVER_TYPE
		if (null != msg.getServerType()) {
			putServerTypeIntoBuffer(msg, buf);
		}
		// added vondart change total length
		buf.putShort(2, (short) buf.position());
		buf.flip();
		return buf.array();
	}

	private void putServerTypeIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverType = msg.getServerType();
		putCommonPartIntoBuffer(buf, SERVER_TYPE, SERVERTYPE_TOTAL_LENGTH);
		if (serverType.length() < SERVERTYPE_VALUE_LENGTH) {
			int len = SERVERTYPE_VALUE_LENGTH - serverType.length();
			for (int i = 0; i < len; i++) {
				serverType += " ";
			}
			buf.put(serverType.getBytes());
		}
	}

	private void putACKTypeIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		boolean ackType = msg.isNeedAcknowledge();
		putCommonPartIntoBuffer(buf, ACK_TYPE, ACKTYPE_TOTAL_LENGTH);
		buf.put(ackType ? (byte) 1 : (byte) 0);
	}

	private void putServerNameIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverName = msg.getServerName();
		putCommonPartIntoBuffer(buf, SERVER_NAME, SERVERNAME_TOTAL_LENGTH);
		if (serverName.length() < SERVERNAME_VALUE_LENGTH) {
			int len = SERVERNAME_VALUE_LENGTH - serverName.length();
			for (int i = 0; i < len; i++) {
				serverName += " ";
			}
			buf.put(serverName.getBytes());
		}
	}

	private void putServerIdIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverId = msg.getServerId();
		putCommonPartIntoBuffer(buf, SERVER_ID, SERVERID_TOTAL_LENGTH);
		if (serverId.length() < SERVERID_VALUE_LENGTH) {
			int len = SERVERID_VALUE_LENGTH - serverId.length();
			for (int i = 0; i < len; i++) {
				serverId += " ";
			}
			buf.put(serverId.getBytes());
		}
	}

	private void putServerIpIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverIp = msg.getServerIp();
		int port = msg.getPort();
		putCommonPartIntoBuffer(buf, SERVER_IP, SERVERIP_TOTAL_LENGTH);
		
		String[] strs = serverIp.split("\\.");
		for (int i = 0; i < strs.length; i++) {
			buf.put((byte)Integer.parseInt(strs[i]));
		}
		buf.putShort(Integer.valueOf(port).byteValue());
		buf.putShort((short)0);
	}

	private void putIntervalIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		int interval = msg.getPeriod();
		putCommonPartIntoBuffer(buf, INTERVAL, INTERVAL_TOTAL_LENGTH);
		buf.putShort(Integer.valueOf(interval).byteValue());
	}

	private void putAccessPasswordIntoBuffer(HeartBeatMessage msg,
			ByteBuffer buf) {
		String accessPassword = msg.getAccessPassword();
		putCommonPartIntoBuffer(buf, PU_PASSWORD, ACCESSPWD_TOTAL_LENGTH);
		if (accessPassword.length() < ACCESSPWD_VALUE_LENGTH) {
			int len = ACCESSPWD_VALUE_LENGTH - accessPassword.length();
			for (int i = 0; i < len; i++) {
				accessPassword += " ";
			}
			buf.put(accessPassword.getBytes());
		}		
	}

	private int getTotalLength(HeartBeatMessage msg) {
		int totalLength = 0;
		totalLength += HEAD_LENGTH;
		totalLength += ACKTYPE_TOTAL_LENGTH;
		if (null != msg.getServerName()) {
			totalLength += SERVERNAME_TOTAL_LENGTH;
		}
		if (null != msg.getServerId()) {
			totalLength += SERVERID_TOTAL_LENGTH;
		}
		if (null != msg.getServerIp()) {
			totalLength += SERVERIP_TOTAL_LENGTH;
		}
		if (null != msg.getServerType()) {
			totalLength += SERVERTYPE_TOTAL_LENGTH;
		}
		if (null != msg.getAccessPassword()) {
			totalLength += ACCESSPWD_TOTAL_LENGTH;
		}
		if (0 != msg.getPeriod()) {
			totalLength += INTERVAL_TOTAL_LENGTH;
		}
		return totalLength;
	}

	/*
	 * 消息属性公共部分:属性类型+保留字+消息属性长度
	 */
	private void putCommonPartIntoBuffer(ByteBuffer buf, int type,
			int totallength) {
		buf.put((byte) type);// 属性类型
		buf.put((byte) RESERVEDVALUE);// 保留字
		buf.putShort((short) totallength);// 消息属性长度
	}
}
